﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ProjectFitus.Models;
using System.Web.Mvc;


namespace ProjectFitus.Models
{
	public class DBFitusRepository : IDBFitusRepository 
	{
		//DataContext sem gefur okkur aðgang að gagnagrunninum
		DBFitusContextDataContext m_db = new DBFitusContextDataContext();

		void IDBFitusRepository.SaveChanges()
		{
			m_db.SubmitChanges();
		}

		//fyrir errors
		void IDBFitusRepository.InsertError(DateTime dt, string source, string stackTrace)
		{
			ErrorLog err = new ErrorLog();
			err.dateOccurred = dt;
			err.controllerName = source;
			err.stackTrace = stackTrace;
			m_db.ErrorLogs.InsertOnSubmit(err);
			m_db.SubmitChanges();
		}

		#region Menuitems
		
		IEnumerable<MenuItem> IDBFitusRepository.GetMenuItemsByParentId(int parentId)
		{
			IEnumerable<MenuItem> mItemList = (from mi in m_db.MenuItems
											   where mi.parentId == parentId
											   orderby mi.menuOrder ascending
											   select mi);
			return mItemList;
		}

		#endregion

		#region SubSite functions

		SubSite IDBFitusRepository.GetSubsiteByTitle(string strTitle)
		{
			SubSite sb = (from ss in m_db.SubSites
						  where ss.title == strTitle
						  select ss).SingleOrDefault();
			return sb;
		}

		SubSite IDBFitusRepository.GetSubsiteById(long subSiteId)
		{
			SubSite subsite = (from ss in m_db.SubSites
						  where ss.id == subSiteId
						  select ss).SingleOrDefault();
			return subsite;
		}

		void IDBFitusRepository.UpdateSubSite(SubSite editedSubSite)
		{
			SubSite currentSubSite = ((IDBFitusRepository)this).GetSubsiteById(editedSubSite.id);
			if (currentSubSite != null)
			{
				currentSubSite.contentText = editedSubSite.contentText;
				currentSubSite.isActive = editedSubSite.isActive;
				currentSubSite.lastDateEdited = editedSubSite.lastDateEdited;
				currentSubSite.lastEditedByUserId = editedSubSite.lastEditedByUserId;
				currentSubSite.title = currentSubSite.title;
				m_db.SubmitChanges();
				//test
			}
		}


		#endregion

		#region Article functions

		IEnumerable<ArticleContent> IDBFitusRepository.GetAllArticlesBySearchString(string strSearch)
		{
			IEnumerable<ArticleContent> articles = (
							from a in m_db.ArticleContents
							where a.contentText.Contains(strSearch)
							|| a.title.Contains(strSearch)
							|| a.introText.Contains(strSearch)
							orderby a.title ascending
							select a);
			return articles;
		}

		void IDBFitusRepository.AddArticle(ArticleContent article)
		{
            m_db.ArticleContents.InsertOnSubmit(article);
            m_db.SubmitChanges();	
		}

		IEnumerable<ArticleContent> IDBFitusRepository.GetAllArticles()
        {
            IEnumerable<ArticleContent> art = (from a in m_db.ArticleContents
									orderby a.title ascending
                                 select a);
            return art;
        }
        
        IEnumerable<long> IDBFitusRepository.GetAuthorsIdsByArticleId(int articleId)
        {
            IEnumerable<long> authorIds = (from a in m_db.ArticleContentUserAuthors
                                          where a.articleContentId == articleId
                                          select a.authorId);
            return authorIds;             
        }

        IEnumerable<string> IDBFitusRepository.GetAuthorsStringByArticleId(int articleId)
        {
            IEnumerable<string> authorString = (from a in m_db.ArticleContentStringAuthors
                                                where a.articleContentId == articleId
                                                select a.authorName);
            return authorString;
        }

		
		ArticleContent IDBFitusRepository.GetArticleById(long id)
        {
            ArticleContent article = (from ac in m_db.ArticleContents
                      where ac.id == id
                      select ac).SingleOrDefault();
            return article;
        }

		void IDBFitusRepository.UpdateArticle(ArticleContent editedArticle)
		{
			ArticleContent currentArticle = ((IDBFitusRepository)this).GetArticleById(editedArticle.id);
			if (currentArticle != null)
			{
				currentArticle.title = editedArticle.title;
				currentArticle.contentText = editedArticle.contentText;
				currentArticle.introText = editedArticle.introText;
				currentArticle.lastEditedByUserId = editedArticle.lastEditedByUserId;
				currentArticle.lastDateEdited = DateTime.Now;
				currentArticle.isActive = editedArticle.isActive;
				//controller þarf að keyra SaveChanges fallið til þar sem þetta er transaction
			}
			//Todo add error logging
		}

		IEnumerable<User> IDBFitusRepository.GetUserAuthorsByArticleId(long articleId)
		{
			IEnumerable<User> authors = from u in m_db.Users
										join a in m_db.ArticleContentUserAuthors
										on u.id equals a.authorId
										where a.articleContentId == articleId
										orderby u.firstName, u.lastName ascending
										select u;
			return authors;

		}

		void IDBFitusRepository.RemoveAuthorFromArticle(long artId, long usrId)
		{
			ArticleContentUserAuthor artUserAuthor = (from au in m_db.ArticleContentUserAuthors
													 where au.authorId == usrId 
													 && au.articleContentId == artId
													select au).SingleOrDefault();
			m_db.ArticleContentUserAuthors.DeleteOnSubmit(artUserAuthor);
		}

		//Sækir categoryid fyrir þann flokk sem frétt er valinn í
		int IDBFitusRepository.GetArticleSelectedCategoryId(long articleId)
		{
			int aId = (from ac in m_db.ArticleToCategories
					   where ac.articleId == articleId
						   select ac.categoryId).FirstOrDefault();
			return aId;
		}

		#endregion

        #region Article Comments

        IEnumerable<ArticleComment> IDBFitusRepository.GetArticleCommentsByArticleId(long articleId)
        {
            IEnumerable<ArticleComment> articleComments = (from ac in m_db.ArticleComments                                                      
                                                   where ac.articleId == articleId
                                                   orderby ac.dateCommented ascending
                                                   select ac);
            return articleComments;
        }

        public void ArticleComment(ArticleComment c)
        {
            c.dateCommented = DateTime.Now;

            m_db.ArticleComments.InsertOnSubmit(c);
            m_db.SubmitChanges();
        }

       // IEnumerable<ArticleComment> GetArticleCommentsByArticalId(long articleId);

		ArticleToCategory IDBFitusRepository.GetArticleToCategoryByIds(long articleId, int categoryId)
		{
			ArticleToCategory articleToCats = (from atc in m_db.ArticleToCategories
										 where atc.categoryId == categoryId
										 && atc.articleId == articleId
										 select atc).FirstOrDefault();
			return articleToCats;
		}

		void IDBFitusRepository.UpdateArticleToCategories(long articleId, int newCategoryId, int oldCategoryId)
		{
			ArticleToCategory oldAtc = ((IDBFitusRepository)this).GetArticleToCategoryByIds(articleId, oldCategoryId);
			ArticleToCategory newAtc = new ArticleToCategory();
			newAtc.categoryId = newCategoryId;
			newAtc.articleId = articleId;
			if (oldCategoryId>0) //just in case, þ.e. ef grein hefur verið skráð án þess að vera í flokk (á ekki að vera hægt en...)
				m_db.ArticleToCategories.DeleteOnSubmit(oldAtc);
			m_db.ArticleToCategories.InsertOnSubmit(newAtc);
			//controller þarf að kalla á saveChanges fallið okkar þar sem þetta er transaction	
		}

        #endregion

        #region Category functions
        /// <summary>
		/// Gets a list of TextContentCategories from
		/// specific parentid and within a specific category type
		/// </summary>
		/// <param name="parentId"></param>
		/// <param name="catTypeid"></param>
		/// <returns></returns>
		IEnumerable<SelectListItem> IDBFitusRepository.GetContentCategoryByParentId(int parentId, int catTypeid)
		{
			IEnumerable<SelectListItem> tcc = from cats in m_db.TextContentCategories
											where cats.categoryTypeId == catTypeid
											&& cats.parentId == parentId
											orderby cats.categoryTitle ascending
											select new SelectListItem {Value = cats.id.ToString(), Text = cats.categoryTitle};
			return tcc;
		}

		IEnumerable<TextContentCategory> IDBFitusRepository.GetTextContentCategoriesByParentId(int parentId, int catTypeid)
		{
			IEnumerable<TextContentCategory> tcc = (from cats in m_db.TextContentCategories
											   where cats.categoryTypeId == catTypeid
											   && cats.parentId == parentId
											   orderby cats.categoryTitle ascending
											   select cats);
			return tcc;
		}


		TextContentCategory IDBFitusRepository.GetCategoryNameById(int id)
		{
			TextContentCategory tcc = (from c in m_db.TextContentCategories
									   where c.id == id
									   select c).SingleOrDefault();
			return tcc;
		}

        IEnumerable<TextContentCategory> IDBFitusRepository.GetAllCategories()
        {
            IEnumerable<TextContentCategory> returnable = from cats in m_db.TextContentCategories
                                                          select cats;
            return returnable;
        }

		#endregion

		#region News functions

		void IDBFitusRepository.AddNews(NewsContent news)
		{
			m_db.NewsContents.InsertOnSubmit(news);
			m_db.SubmitChanges();
		}

		IEnumerable<NewsContent> IDBFitusRepository.GetNewsByCategoryId(int id)
		{
			//TODO á eftir að útfæra, vantar venslatöflu milli greinar og flokks
			IEnumerable<NewsContent> newsCollection = from n in m_db.NewsContents
													  join j in m_db.NewsToCategories
													  on n.id equals j.newsId
													  where j.categoryId == id
													  orderby n.dateCreated descending
													  select n;
														  //where n.id == m_db.
			return newsCollection;
		}

		IEnumerable<NewsContent> IDBFitusRepository.GetNews(int count)
		{
			IEnumerable<NewsContent> newsContent = (from nc in m_db.NewsContents
													orderby nc.dateCreated descending
													select nc).Take(count);
			return newsContent;
		}

		IEnumerable<NewsContent> IDBFitusRepository.GetAllNews()
		{
			IEnumerable<NewsContent> newsContent = (from nc in m_db.NewsContents
													join j in m_db.NewsToCategories
													on nc.id equals j.newsId
													where j.categoryId != 28
												   orderby nc.dateCreated descending
												   select nc);
			return newsContent;

		}

		NewsContent IDBFitusRepository.GetNewsById(long id)
        {
            NewsContent newsContent = (from nc in m_db.NewsContents
											where nc.id == id
									   select nc).SingleOrDefault();
            return newsContent;
        }

		void IDBFitusRepository.UpdateNews(NewsContent editedNews)
		{
			NewsContent currentNews = ((IDBFitusRepository)this).GetNewsById(editedNews.id);
			if (currentNews != null)
			{
				currentNews.contentText = editedNews.contentText;
				currentNews.introText = editedNews.introText;
				currentNews.lastEditedByUserId = editedNews.lastEditedByUserId;
				currentNews.title = editedNews.title;
				currentNews.lastDateEdited = DateTime.Now;
				currentNews.isActive = editedNews.isActive;
				//controller þarf að keyra SaveChanges fallið til þar sem þetta er transaction
			}
            //Todo add error logging
		}

		//Sækir categoryid fyrir þann flokk sem frétt er valinn í
		int IDBFitusRepository.GetNewsSelectedCategoryId(long newsId)
		{
			int nId = (from nc in m_db.NewsToCategories
					  where nc.newsId == newsId
						   select nc.categoryId).FirstOrDefault();
			return nId;
		}

		NewsToCategory IDBFitusRepository.GetNewsToCategoryByIds(long newsId, int categoryId)
		{
			NewsToCategory newsToCats = (from ntc in m_db.NewsToCategories
										where ntc.categoryId == categoryId
										&& ntc.newsId == newsId
										select ntc).FirstOrDefault();
			return newsToCats;
		}

		void IDBFitusRepository.AddNewsToCategories(NewsToCategory newNtc)
		{
			m_db.NewsToCategories.InsertOnSubmit(newNtc);
			//controller þarf að kalla á saveChanges fallið okkar þar sem þetta er transaction	
		}

		void IDBFitusRepository.UpdateNewsToCategories(long newsId, int newCategoryId, int oldCategoryId)
		{
			NewsToCategory oldNtc = ((IDBFitusRepository)this).GetNewsToCategoryByIds(newsId, oldCategoryId);
			NewsToCategory newNtc = new NewsToCategory();
			newNtc.categoryId = newCategoryId;
			newNtc.newsId = newsId;
			if (oldCategoryId > 0) //just in case, þ.e. ef frétt hefur verið skráð án þess að vera í flokk (á ekki að vera hægt en...)
				m_db.NewsToCategories.DeleteOnSubmit(oldNtc);
			m_db.NewsToCategories.InsertOnSubmit(newNtc);
			//controller þarf að kalla á saveChanges fallið okkar þar sem þetta er transaction	
		}
		#endregion

		#region User functions

		long IDBFitusRepository.GetUserIdByAspNetUsrId(Guid aspNetUserId)
		{
			long id = (from uid in m_db.Users
					   where uid.aspnetUserId == aspNetUserId
					   select uid.id).SingleOrDefault();
			return id;
		}

		User IDBFitusRepository.GetUserById(long usrId)
		{
			User usr = (from u in m_db.Users
						where u.id == usrId
						select u).SingleOrDefault();
			return usr;
		}

		// Add new User
		void IDBFitusRepository.AddNewUser(string usr, string email)
		{
			User webuser = new User();
			webuser.email = email;
			webuser.userName = usr;
			webuser.isActive = true;
			webuser.verificationCode = "bla";
			m_db.Users.InsertOnSubmit(webuser);
			m_db.SubmitChanges();
		}
        void IDBFitusRepository.UpdateUser(User usr)
        {
			User updateable = ((IDBFitusRepository)this).GetUserById(usr.id);
            if (updateable != null)
            {
                updateable = usr;
                //updateable.firstName = usr.firstName;
                //updateable.lastName = usr.lastName;
                //updateable.email = usr.email;
                //updateable.userName = usr.userName;
                //updateable.userDescription = usr.userDescription;
                //updateable.country = usr.country;
                //updateable.dateOfBirth = usr.dateOfBirth;
                //updateable.profileImageUrl = usr.profileImageUrl; þarf þetta ?
                m_db.SubmitChanges();
            }
            //Add exception logic
        }

		IEnumerable<User> IDBFitusRepository.GetAllUsers()
		{
			IEnumerable<User> usrCollection = (from u in m_db.Users
												orderby u.userName
											   select u);
			return usrCollection;
		}

		IEnumerable<User> IDBFitusRepository.GetAllUsersWithNames()
		{
			IEnumerable<User> usrCollection = (from u in m_db.Users
								where u.firstName.Length > 0
								&& u.lastName.Length > 0
								orderby u.firstName, u.lastName ascending
								select u);
			return usrCollection;
		}

		IEnumerable<SelectListItem> IDBFitusRepository.GetAllUsersAsSelList()
		{
			IEnumerable<SelectListItem> usrCollection = (from u in m_db.Users
										where u.firstName.Length > 0
										&& u.lastName.Length > 0
										orderby u.firstName, u.lastName ascending
										select new SelectListItem { Value = u.id.ToString(), Text = (u.firstName + " " + u.lastName) });
			return usrCollection;
		}
     
		#endregion

        #region Profession functions

		IEnumerable<ProfessionListItem> IDBFitusRepository.GetAllProfessions()
        {
            IEnumerable<ProfessionListItem> pro = from professions in m_db.ProfessionListItems
                                          select professions;
            return pro;
        }

        List<SelectListItem> IDBFitusRepository.GetAllProfessionsViaSelectListItems()
        {
			IEnumerable<ProfessionListItem> toSelectList = ((IDBFitusRepository)this).GetAllProfessions();
            
            List<SelectListItem> returnable = new List<SelectListItem>();          
            
            foreach (var i in toSelectList)
            {
                returnable.Add(new SelectListItem{Text = i.profTitle, Value = i.id.ToString()});
            }

            return returnable;
        }
        

        #endregion

        #region Specialist functions

		Specialist IDBFitusRepository.GetSpecialistById(long id)
        {
            Specialist returnable = (from special in m_db.Specialists
                                     where id == special.id
                                     select special).SingleOrDefault();
            return returnable;
        }

		IEnumerable<Specialist> IDBFitusRepository.GetAllSpecialists()
        {
            IEnumerable<Specialist> TheSpecialOnes = from specialists in m_db.Specialists
                                                     select specialists;
            return TheSpecialOnes;
        }

		void IDBFitusRepository.InsertNewSpecialist(Specialist specs)
        {
            m_db.Specialists.InsertOnSubmit(specs);
            m_db.SubmitChanges();
        }

		void IDBFitusRepository.UpdateSpecialist(Specialist specs)
        {
			Specialist updateable = ((IDBFitusRepository)this).GetSpecialistById(specs.id);
            if (updateable != null)
            {
                updateable = specs;
                m_db.SubmitChanges();
            }
            //Add exception logic
        }

        #endregion

        #region Request functions

        #region MainRequest functions

        IEnumerable<Request> IDBFitusRepository.GetAllRequests()
        {
            IEnumerable<Request> LeRequests = from reqs in m_db.Requests
                                              select reqs;
            return LeRequests;
        }

		Request IDBFitusRepository.GetRequestById(long id)
        {
            Request returnable = (from reqs in m_db.Requests
                                  where id == reqs.id
                                  select reqs).SingleOrDefault();
            return returnable;
        }


		void IDBFitusRepository.CreateRequest(Request req)
        {
            m_db.Requests.InsertOnSubmit(req);
            m_db.SubmitChanges();
        }

		void IDBFitusRepository.UpdateRequest(Request req)
        {
			Request updateable = ((IDBFitusRepository)this).GetRequestById(req.id);
            if (updateable != null)
            {
                updateable = req;
                m_db.SubmitChanges();
            }
            //Todo Add error logging
        }
        /// <summary>
        /// Grabs the p-th page of requests. The page sizes are calculated from n.
        /// </summary>
        /// <param name="n">Number of items per page</param>
        /// <param name="p">Page number</param>
        /// <returns></returns>
		IEnumerable<Request> IDBFitusRepository.Get_n_MostRecentRequestsAtPage_p(int n, int p)
        {
            IEnumerable<Request> returnable = (from reqs in m_db.Requests
                                               orderby reqs.dateCreated descending
                                               select reqs).Skip(p * n).Take(n);
            return returnable;
        }

        #endregion

        #region RequestResponse functions

        IEnumerable<RequestResponse> IDBFitusRepository.GetAllRequestResponsesByRequestId(long requestId)
        {
            IEnumerable<RequestResponse> returnable = from reqResps in m_db.RequestResponses
                                                      where reqResps.requestId == requestId
                                                      orderby reqResps.dateCreated ascending
                                                      select reqResps;
            return returnable;
        }

        //Útfæra þetta fall með því að nota þetta fyrir ofan?
        IEnumerable<RequestResponse> IDBFitusRepository.GetAllActiveRequestResponsesByRequestId(long requestId)
        {
            IEnumerable<RequestResponse> returnable = from reqResps in m_db.RequestResponses
                                                      where reqResps.requestId == requestId && reqResps.isActive == true
                                                      orderby reqResps.dateCreated ascending
                                                      select reqResps;
            return returnable;
        }

        void IDBFitusRepository.AddRequestResponse(RequestResponse reqresp)
        {
            m_db.RequestResponses.InsertOnSubmit(reqresp);
            m_db.SubmitChanges();
        }

        void IDBFitusRepository.DeReActivateRequestResponse(long responseId)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region RequestType functions

        IEnumerable<RequestType> IDBFitusRepository.GetAllRequestTypes()
        {
            IEnumerable<RequestType> returnable = from typesOfRequests in m_db.RequestTypes
                                                  select typesOfRequests;
            return returnable;
        }

        List<SelectListItem> IDBFitusRepository.GetAllRequestTypesViaSelectListItems()
        {
            IEnumerable<RequestType> toSelectList = ((IDBFitusRepository)this).GetAllRequestTypes();

            List<SelectListItem> returnable = new List<SelectListItem>();

            foreach (var i in toSelectList)
            {
                returnable.Add(new SelectListItem { Text = i.requestTypeName, Value = i.id.ToString() });
            }

            return returnable;

        }

        #endregion

        #endregion

        #region AssignmentStatusList functions

        IEnumerable<AssignmentStatusListItem> IDBFitusRepository.GetAllStatusNames()
        {
            IEnumerable<AssignmentStatusListItem> returnable =  from status in m_db.AssignmentStatusListItems
                                                    select status;
            return returnable;
        }

        List<SelectListItem> IDBFitusRepository.GetAllStatusNamesViaSelectListItems()
        {
            IEnumerable<AssignmentStatusListItem> toSelectList = ((IDBFitusRepository)this).GetAllStatusNames();
            List<SelectListItem> returnable = new List<SelectListItem>();

            foreach (var i in toSelectList)
            {
                returnable.Add(new SelectListItem{Text = i.statusName, Value = i.id.ToString()});
            }

            return returnable;
        }

        #endregion

        #region FitusLogger function

        void IDBFitusRepository.LoggError(ErrorLog ex)
        {
            m_db.ErrorLogs.InsertOnSubmit(ex);
            m_db.SubmitChanges();
        }

        #endregion
        
    }
}